package com.wltt.product.ahuthr.service;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wltt.product.ahuthr.component.FlowComponent;
import com.wltt.product.ahuthr.component.SalaryComponent;
import com.wltt.product.ahuthr.config.exception.BusinessException;
import com.wltt.product.ahuthr.constants.YearConstant;
import com.wltt.product.ahuthr.constants.YesNoConstant;
import com.wltt.product.ahuthr.enums.*;
import com.wltt.product.ahuthr.excel.SalaryExportHandler;
import com.wltt.product.ahuthr.mapper.*;
import com.wltt.product.ahuthr.model.ResultData;
import com.wltt.product.ahuthr.model.RspPage;
import com.wltt.product.ahuthr.model.bo.ListUserDetailSalaryBO;
import com.wltt.product.ahuthr.model.bo.ListUserSalaryBO;
import com.wltt.product.ahuthr.model.po.*;
import com.wltt.product.ahuthr.model.vo.*;
import com.wltt.product.ahuthr.model.vo.base.*;
import com.wltt.product.ahuthr.service.base.BaseServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * @ClassName: SalaryServiceImpl
 * @Description: 逻辑服务类<br />
 * 不做业务校验，参数校验统一放到前置的Service中
 * @Date: 2024-05-30 14:34:21
 * @Author yanggl
 */
@Service(value = "salaryService")
public class SalaryServiceImpl extends BaseServiceImpl<SalaryPO, Long> implements SalaryService {

    private static final BigDecimal salary_1 = BigDecimal.valueOf(1);

    private SalaryMapper salaryMapper;

    @Resource
    private UserBasicMapper userBasicMapper;

    @Resource
    private SalaryFileMapper salaryFileMapper;

    @Resource
    private SalaryLevelMapper salaryLevelMapper;

    @Resource
    private SalaryManageMapper salaryManageMapper;

    @Resource
    private SalaryOneMapper salaryOneMapper;

    @Resource
    private SalaryTwoMapper salaryTwoMapper;

    @Resource
    private SalarySubsidyMapper salarySubsidyMapper;

    @Resource
    private SalaryHouseFundMapper salaryHouseFundMapper;

    @Resource
    private SalaryInsuranceMapper salaryInsuranceMapper;

    @Resource
    private SalaryRetireMapper salaryRetireMapper;

    @Resource
    private SystemPostMapper systemPostMapper;

    @Resource
    private SystemPostSalaryMapper systemPostSalaryMapper;

    @Resource
    private SystemLevelSalaryMapper systemLevelSalaryMapper;
    @Resource
    private SystemPostTypeMapper systemPostTypeMapper;

    @Resource
    private SalaryComponent salaryComponent;

    @Resource
    private FlowComponent flowComponent;


    //构造方法
    public SalaryServiceImpl(SalaryMapper salaryMapper) {
        super(salaryMapper);
        this.salaryMapper = salaryMapper;
    }

    @Override
    public ResultData listUserSalary(ListUserSalaryReq listUserSalaryReq) {
        String orderBy = "user_arrival_date desc";
        Page page = PageHelper.startPage(listUserSalaryReq.getPageNo(), listUserSalaryReq.getPageSize(), orderBy);

        UserBasicPO userBasicPO = new UserBasicPO();
        BeanUtils.copyProperties(listUserSalaryReq, userBasicPO);
        List<ListUserSalaryBO> bos = userBasicMapper.listUserSalary(userBasicPO);

        List<ListUserSalaryRsp> rsps = Optional.ofNullable(bos).orElse(new ArrayList<>())
                .stream().map(bo -> {
                    ListUserSalaryRsp rsp = new ListUserSalaryRsp();
                    BeanUtils.copyProperties(bo, rsp);
                    return rsp;
                }).collect(Collectors.toList());
        RspPage rspPage = new RspPage(listUserSalaryReq.getPageNo(), listUserSalaryReq.getPageSize(), rsps, page.getTotal());
        return ResultData.success(rspPage);
    }

    /**
     * 导出
     *
     * @param response
     * @return
     */
    @Override
    public void exportSalary(HttpServletResponse response) {
        List<ListUserDetailSalaryBO> listUserDetailSalaryBOS = salaryMapper.listUserDetailSalary();

        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("薪资信息" + System.currentTimeMillis(), "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), ListUserDetailSalaryBO.class)
                    .registerWriteHandler(new SalaryExportHandler())
                    .autoCloseStream(Boolean.FALSE).sheet("明细")
                    .doWrite(listUserDetailSalaryBOS);
        } catch (Exception e) {
            response.reset();
            throw new BusinessException("导出失败,请稍后重试", HttpStatus.BAD_REQUEST);
        }
    }

    /**
     * 分页查询未起薪人员
     *
     * @param listUserNoSalaryReq
     * @return
     */
    @Override
    public ResultData listUserNoSalary(ListUserNoSalaryReq listUserNoSalaryReq) {

        String orderBy = "user_arrival_date desc";
        Page page = PageHelper.startPage(listUserNoSalaryReq.getPageNo(), listUserNoSalaryReq.getPageSize(), orderBy);

        UserBasicPO userBasicPO = new UserBasicPO();
        BeanUtils.copyProperties(listUserNoSalaryReq, userBasicPO);
        List<ListUserSalaryBO> bos = userBasicMapper.listUserNoSalary(userBasicPO);

        List<ListUserSalaryRsp> rsps = Optional.ofNullable(bos).orElse(new ArrayList<>())
                .stream().map(bo -> {
                    ListUserSalaryRsp rsp = new ListUserSalaryRsp();
                    BeanUtils.copyProperties(bo, rsp);
                    return rsp;
                }).collect(Collectors.toList());
        RspPage rspPage = new RspPage(listUserNoSalaryReq.getPageNo(), listUserNoSalaryReq.getPageSize(), rsps, page.getTotal());
        return ResultData.success(rspPage);
    }

    /**
     * 薪资详情
     *
     * @param salaryDetailReq
     * @return
     */
    @Override
    public ResultData salaryDetail(SalaryDetailReq salaryDetailReq) {
        Long userId = salaryDetailReq.getUserId();
        if (null == userId) {
            throw new BusinessException("未指定人员", HttpStatus.BAD_REQUEST);
        }

//        UserBasicPO userBasicPO = userBasicMapper.queryById(userId);
//        if (null == userBasicPO) {
//            throw new BusinessException("人员不存在", HttpStatus.BAD_REQUEST);
//        }
//        UserSimpleVO userSimpleVO = new UserSimpleVO();
//        BeanUtils.copyProperties(userBasicPO, userSimpleVO);
//        if (null != userBasicPO.getDeptId()) {
//            DeptPO deptPO = deptMapper.queryById(userBasicPO.getDeptId());
//            if (null != deptPO) {
//                userSimpleVO.setDeptName(deptPO.getDeptName());
//            }
//        }

        // 返回对象
        SalaryDetailRsp salaryDetailRsp = new SalaryDetailRsp();
//        salaryDetailRsp.setUserSimple(userSimpleVO);

        SalaryPO salaryPO = salaryMapper.queryByUserId(userId);
        if (null == salaryPO) {
            throw new BusinessException("未找到该人员薪资信息", HttpStatus.BAD_REQUEST);
        }
        BeanUtils.copyProperties(salaryPO, salaryDetailRsp);

        // 档案薪资
        SalaryFilePO salaryFilePO = salaryFileMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryFilePO) {
            salaryFilePO = new SalaryFilePO();
        }
        SalaryFileVO salaryFileVO = new SalaryFileVO();
        BeanUtils.copyProperties(salaryFilePO, salaryFileVO);
        salaryDetailRsp.setSalaryFile(salaryFileVO);

        // 薪级薪资
        SalaryLevelPO salaryLevelPO = salaryLevelMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryLevelPO) {
            salaryLevelPO = new SalaryLevelPO();
        }
        SalaryLevelVO salaryLevelVO = new SalaryLevelVO();
        BeanUtils.copyProperties(salaryLevelPO, salaryLevelVO);
        salaryDetailRsp.setSalaryLevel(salaryLevelVO);

        // 管理责任
        SalaryManagePO salaryManagePO = salaryManageMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryManagePO) {
            salaryManagePO = new SalaryManagePO();
        }
        SalaryManageVO salaryManageVO = new SalaryManageVO();
        BeanUtils.copyProperties(salaryManagePO, salaryManageVO);
        salaryDetailRsp.setSalaryManage(salaryManageVO);

        // 第一部分
        SalaryOnePO salaryOnePO = salaryOneMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryOnePO) {
            salaryOnePO = new SalaryOnePO();
        }
        SalaryOneVO salaryOneVO = new SalaryOneVO();
        BeanUtils.copyProperties(salaryOnePO, salaryOneVO);
        salaryDetailRsp.setSalaryOne(salaryOneVO);

        // 第二部分
        SalaryTwoPO salaryTwoPO = salaryTwoMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryTwoPO) {
            salaryTwoPO = new SalaryTwoPO();
        }
        SalaryTwoVO salaryTwoVO = new SalaryTwoVO();
        BeanUtils.copyProperties(salaryTwoPO, salaryTwoVO);
        salaryDetailRsp.setSalaryTwo(salaryTwoVO);

        // 补贴
        SalarySubsidyPO salarySubsidyPO = salarySubsidyMapper.queryBySalaryId(salaryPO.getId());
        if (null == salarySubsidyPO) {
            salarySubsidyPO = new SalarySubsidyPO();
        }
        SalarySubsidyVO salarySubsidyVO = new SalarySubsidyVO();
        BeanUtils.copyProperties(salarySubsidyPO, salarySubsidyVO);
        salaryDetailRsp.setSalarySubsidy(salarySubsidyVO);

        // 住房公积金
        List<SalaryHouseFundPO> salaryHouseFundPOs = salaryHouseFundMapper.queryBySalaryId(salaryPO.getId());
        List<SalaryHouseFundVO> vos = Optional.ofNullable(salaryHouseFundPOs).orElse(new ArrayList<>())
                .stream().map(po -> {
                    SalaryHouseFundVO vo = new SalaryHouseFundVO();
                    BeanUtils.copyProperties(po, vo);
                    return vo;
                }).collect(Collectors.toList());
        salaryDetailRsp.setSalaryHouseFunds(vos);

        // 社保
        SalaryInsurancePO salaryInsurancePO = salaryInsuranceMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryInsurancePO) {
            salaryInsurancePO = new SalaryInsurancePO();
        }
        SalaryInsuranceVO salaryInsuranceVO = new SalaryInsuranceVO();
        BeanUtils.copyProperties(salaryInsurancePO, salaryInsuranceVO);
        salaryDetailRsp.setSalaryInsurance(salaryInsuranceVO);


        // 退休待遇
        SalaryRetirePO salaryRetirePO = salaryRetireMapper.queryBySalaryId(salaryPO.getId());
        if (null == salaryRetirePO) {
            salaryRetirePO = new SalaryRetirePO();
        }
        SalaryRetireVO salaryRetireVO = new SalaryRetireVO();
        BeanUtils.copyProperties(salaryRetirePO, salaryRetireVO);
        salaryDetailRsp.setSalaryRetire(salaryRetireVO);
        return ResultData.success(salaryDetailRsp);
    }

    /**
     * 计算薪资
     *
     * @param calculateSalaryReq
     * @return
     */
    @Override
    public ResultData calculateSalary(CalculateSalaryReq calculateSalaryReq) {

        Long postId = calculateSalaryReq.getPostId();
        Long levelId = calculateSalaryReq.getLevelId();
        if (null == postId && null == levelId) {
            throw new BusinessException("岗位和薪级至少指定一个", HttpStatus.BAD_REQUEST);
        }

        SystemPostTypePO systemPostTypePO = null;

        CalculateSalaryRsp calculateSalaryRsp = new CalculateSalaryRsp();
        // 岗位相关工资
        if (null != postId) {
            SystemPostPO systemPostPO = systemPostMapper.queryById(postId);
            if (null == systemPostPO) {
                throw new BusinessException("岗位不存在", HttpStatus.BAD_REQUEST);
            }
            systemPostTypePO = systemPostTypeMapper.queryById(systemPostPO.getPostTypeId());

            SystemPostSalaryPO systemPostSalaryPO = systemPostSalaryMapper.queryByPostIdAndModifyYear(postId, YearConstant.YEAR_2021);
            if (null == systemPostSalaryPO) {
                throw new BusinessException("无法找到该岗位薪资信息", HttpStatus.BAD_REQUEST);
            }

            calculateSalaryRsp.setPostName(systemPostPO.getPostName());
            calculateSalaryRsp.setPostRankName(systemPostPO.getPostRankName());
            calculateSalaryRsp.setPostDescribe(systemPostTypePO.getPostTypeName() + "-" + systemPostPO.getPostRankName() + "-" + systemPostPO.getPostName());
            calculateSalaryRsp.setPostSalary(BigDecimal.valueOf(systemPostSalaryPO.getPostSalary() / 100.00));
            calculateSalaryRsp.setBasicAllowance(BigDecimal.valueOf(systemPostSalaryPO.getBasicAllowance() / 100.00));
            calculateSalaryRsp.setPostAllowance(BigDecimal.valueOf(systemPostSalaryPO.getPostAllowance() / 100.00));
            calculateSalaryRsp.setAchievementAward(BigDecimal.valueOf(systemPostSalaryPO.getAchievementAward() / 100.00));
            calculateSalaryRsp.setPerformanceAward(BigDecimal.valueOf(systemPostSalaryPO.getPerformanceAward() / 100.00));
            calculateSalaryRsp.setManager(systemPostPO.getPostName());
            calculateSalaryRsp.setManageAllowance(BigDecimal.valueOf(systemPostSalaryPO.getManageAllowance() / 100.00));
        }

        // 薪级相关工资
        if (null != levelId) {
            SystemLevelSalaryPO systemLevelSalaryPO = systemLevelSalaryMapper.queryById(levelId);
            if (null == systemLevelSalaryPO) {
                throw new BusinessException("薪级不存在", HttpStatus.BAD_REQUEST);
            }
            if (null == systemPostTypePO) {
                systemPostTypePO = systemPostTypeMapper.queryById(systemLevelSalaryPO.getPostTypeId());
            }
            if (null == calculateSalaryRsp.getPostDescribe()) {
                calculateSalaryRsp.setPostDescribe(systemPostTypePO.getPostTypeName());
            }
            calculateSalaryRsp.setLevelDescribe("系列: " + systemPostTypePO.getPostTypeName() + "，薪级: " + systemLevelSalaryPO.getLevelRank());
            calculateSalaryRsp.setLevelRank(systemLevelSalaryPO.getLevelRank());
            calculateSalaryRsp.setSalaryStandard(BigDecimal.valueOf(systemLevelSalaryPO.getSalaryStandard() / 100.00));
        }

        return ResultData.success(calculateSalaryRsp);
    }

    /**
     * 计算公积金
     *
     * @param calculateHouseFundsReq
     * @return
     */
    @Override
    public ResultData calculateHouseFunds(CalculateHouseFundsReq calculateHouseFundsReq) {
        Long postId = calculateHouseFundsReq.getPostId();
        Long levelId = calculateHouseFundsReq.getLevelId();
        if (null == postId) {
            throw new BusinessException("请先选择岗位", HttpStatus.BAD_REQUEST);
        }
        if (null == levelId) {
            throw new BusinessException("请先选择薪级", HttpStatus.BAD_REQUEST);
        }

        SystemPostPO systemPostPO = systemPostMapper.queryById(postId);
        if (null == systemPostPO) {
            throw new BusinessException("岗位不存在", HttpStatus.BAD_REQUEST);
        }
        SystemPostSalaryPO systemPostSalaryPO = systemPostSalaryMapper.queryByPostIdAndModifyYear(postId, YearConstant.YEAR_2021);
        if (null == systemPostSalaryPO) {
            throw new BusinessException("无法找到该岗位薪资信息", HttpStatus.BAD_REQUEST);
        }
        SystemLevelSalaryPO systemLevelSalaryPO = systemLevelSalaryMapper.queryById(levelId);
        if (null == systemLevelSalaryPO) {
            throw new BusinessException("薪级不存在", HttpStatus.BAD_REQUEST);
        }

        // 返回对象
        CalculateHouseFundsRsp calculateHouseFundsRsp = new CalculateHouseFundsRsp();

        // 公积金基数
        Double fundCardinalResult = systemPostSalaryPO.getPostSalary() / 100.00 + systemLevelSalaryPO.getSalaryStandard() / 100.00 + systemPostSalaryPO.getBasicAllowance() / 100.00 + systemPostSalaryPO.getPostAllowance() / 100.00
                + (systemPostSalaryPO.getBasicAllowance() / 100.00 + systemPostSalaryPO.getPostAllowance() / 100.00) / 0.6 * 0.4 + systemPostSalaryPO.getPerformanceAward() / 100.00
                + 1650 + (systemPostSalaryPO.getPostSalary() / 100.00 + systemLevelSalaryPO.getSalaryStandard() / 100.00) / 12;
        BigDecimal fundCardinal = BigDecimal.valueOf(fundCardinalResult).setScale(0, RoundingMode.CEILING);
        calculateHouseFundsRsp.setFundCardinal(fundCardinal);

        // 公积金基数计算公式
        StringBuilder fundCardinalFormula_sb = new StringBuilder();
        fundCardinalFormula_sb.append("ROUNDUP(");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getPostSalary() / 100);
        fundCardinalFormula_sb.append("+");
        fundCardinalFormula_sb.append(systemLevelSalaryPO.getSalaryStandard() / 100);
        fundCardinalFormula_sb.append("+");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getBasicAllowance() / 100);
        fundCardinalFormula_sb.append("+");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getPostAllowance() / 100);
        fundCardinalFormula_sb.append("+(");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getBasicAllowance() / 100);
        fundCardinalFormula_sb.append("+");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getPostAllowance() / 100);
        fundCardinalFormula_sb.append(")/0.6*0.4");
        fundCardinalFormula_sb.append("+");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getPerformanceAward() / 100);
        fundCardinalFormula_sb.append("+1650+(");
        fundCardinalFormula_sb.append(systemPostSalaryPO.getPostSalary() / 100);
        fundCardinalFormula_sb.append("+");
        fundCardinalFormula_sb.append(systemLevelSalaryPO.getSalaryStandard() / 100);
        fundCardinalFormula_sb.append(")/12,0)=");
        fundCardinalFormula_sb.append(fundCardinal);
        calculateHouseFundsRsp.setFundCardinalFormula(fundCardinalFormula_sb.toString());

        // 公积金标准
        BigDecimal fundStandardResult = fundCardinal.multiply(new BigDecimal("0.12"));
        BigDecimal fundStandard = fundStandardResult.setScale(0, RoundingMode.HALF_UP);
        calculateHouseFundsRsp.setFundStandard(fundStandard);

        // 公积金标准计算公式
        StringBuilder fundStandardFormula_sb = new StringBuilder();
        fundStandardFormula_sb.append("ROUND(");
        fundStandardFormula_sb.append(fundCardinal);
        fundStandardFormula_sb.append("*0.12,0)=");
        fundStandardFormula_sb.append(fundStandard);
        calculateHouseFundsRsp.setFundStandardFormula(fundStandardFormula_sb.toString());

        return ResultData.success(calculateHouseFundsRsp);
    }

    /**
     * 计算社保
     *
     * @param calculateInsuranceReq
     * @return
     */
    @Override
    public ResultData calculateInsurance(CalculateInsuranceReq calculateInsuranceReq) {
        Long postId = calculateInsuranceReq.getPostId();
        Long levelId = calculateInsuranceReq.getLevelId();
        Integer governmentStaff = calculateInsuranceReq.getGovernmentStaff();
        if (null == postId) {
            throw new BusinessException("请先选择岗位", HttpStatus.BAD_REQUEST);
        }
        if (null == levelId) {
            throw new BusinessException("请先选择薪级", HttpStatus.BAD_REQUEST);
        }
        if (null == governmentStaff) {
            throw new BusinessException("请先选择是否编制内", HttpStatus.BAD_REQUEST);
        }

        SystemPostPO systemPostPO = systemPostMapper.queryById(postId);
        if (null == systemPostPO) {
            throw new BusinessException("岗位不存在", HttpStatus.BAD_REQUEST);
        }

        SystemPostSalaryPO systemPostSalaryPO = systemPostSalaryMapper.queryByPostIdAndModifyYear(postId, YearConstant.YEAR_2021);
        if (null == systemPostSalaryPO) {
            throw new BusinessException("无法找到该岗位薪资信息", HttpStatus.BAD_REQUEST);
        }
        SystemLevelSalaryPO systemLevelSalaryPO = systemLevelSalaryMapper.queryById(levelId);
        if (null == systemLevelSalaryPO) {
            throw new BusinessException("薪级不存在", HttpStatus.BAD_REQUEST);
        }

        CalculateInsuranceRsp calculateInsuranceRsp = new CalculateInsuranceRsp();

        // 社保基数
        Double socialCardinalResult;
        BigDecimal socialCardinal;
        StringBuilder socialCardinalFormula_sb = new StringBuilder();
        if (GovernmentStaffEnum.YES.getCode() == governmentStaff) {
            socialCardinalResult = systemPostSalaryPO.getPostSalary() / 100.00 + systemLevelSalaryPO.getSalaryStandard() / 100.00
                    + (systemPostSalaryPO.getBasicAllowance() / 100.00 + systemPostSalaryPO.getPostAllowance() / 100.00) / 0.7;
            socialCardinal = BigDecimal.valueOf(socialCardinalResult).setScale(0, RoundingMode.CEILING);
            socialCardinalFormula_sb.append("ROUNDUP(");
            socialCardinalFormula_sb.append(systemPostSalaryPO.getPostSalary() / 100);
            socialCardinalFormula_sb.append("+");
            socialCardinalFormula_sb.append(systemLevelSalaryPO.getSalaryStandard() / 100);
            socialCardinalFormula_sb.append("+(");
            socialCardinalFormula_sb.append(systemPostSalaryPO.getBasicAllowance() / 100);
            socialCardinalFormula_sb.append("+");
            socialCardinalFormula_sb.append(systemPostSalaryPO.getPostAllowance() / 100);
            socialCardinalFormula_sb.append(")/0.7,2)=");
        } else {
            socialCardinalResult = systemPostSalaryPO.getPostSalary() / 100.00 + systemLevelSalaryPO.getSalaryStandard() / 100.00
                    + systemPostSalaryPO.getBasicAllowance() / 100.00 + systemPostSalaryPO.getPostAllowance() / 100.00
                    + systemPostSalaryPO.getPerformanceAward() / 100.00;
            socialCardinal = BigDecimal.valueOf(socialCardinalResult).setScale(0, RoundingMode.CEILING);
            socialCardinalFormula_sb.append(systemPostSalaryPO.getPostSalary() / 100);
            socialCardinalFormula_sb.append("+");
            socialCardinalFormula_sb.append(systemLevelSalaryPO.getSalaryStandard() / 100);
            socialCardinalFormula_sb.append("+");
            socialCardinalFormula_sb.append(systemPostSalaryPO.getBasicAllowance() / 100);
            socialCardinalFormula_sb.append("+");
            socialCardinalFormula_sb.append(systemPostSalaryPO.getPostAllowance() / 100);
            socialCardinalFormula_sb.append("+");
            socialCardinalFormula_sb.append(systemPostSalaryPO.getPerformanceAward() / 100);
            socialCardinalFormula_sb.append("=");
        }
        calculateInsuranceRsp.setSocialCardinal(socialCardinal);
        socialCardinalFormula_sb.append(socialCardinal);
        calculateInsuranceRsp.setSocialCardinalFormula(socialCardinalFormula_sb.toString());

        // 养老基数
        calculateInsuranceRsp.setEndowmentCardinal(socialCardinal);
        calculateInsuranceRsp.setEndowmentCardinalFormula(calculateInsuranceRsp.getSocialCardinalFormula());


        // 医保基数
        Double medicalCardinalResult = systemPostSalaryPO.getPostSalary() / 100.00 + systemLevelSalaryPO.getSalaryStandard() / 100.00
                + systemPostSalaryPO.getBasicAllowance() / 100.00 + systemPostSalaryPO.getPostAllowance() / 100.00;
        BigDecimal medicalCardinal = BigDecimal.valueOf(medicalCardinalResult).setScale(0, RoundingMode.CEILING);
        StringBuilder medicalCardinalFormula_sb = new StringBuilder();
        medicalCardinalFormula_sb.append(systemPostSalaryPO.getPostSalary() / 100);
        medicalCardinalFormula_sb.append("+");
        medicalCardinalFormula_sb.append(systemLevelSalaryPO.getSalaryStandard() / 100);
        medicalCardinalFormula_sb.append("+");
        medicalCardinalFormula_sb.append(systemPostSalaryPO.getBasicAllowance() / 100);
        medicalCardinalFormula_sb.append("+");
        medicalCardinalFormula_sb.append(systemPostSalaryPO.getPostAllowance() / 100);
        medicalCardinalFormula_sb.append("=");
        medicalCardinalFormula_sb.append(medicalCardinal);
        calculateInsuranceRsp.setMedicalCardinal(medicalCardinal);
        calculateInsuranceRsp.setMedicalCardinalFormula(medicalCardinalFormula_sb.toString());

        // 医保
        BigDecimal medicalInsurance = medicalCardinal.multiply(new BigDecimal("0.02"));
        calculateInsuranceRsp.setMedicalInsurance(medicalInsurance);
        StringBuilder medicalInsuranceFormula_sb = new StringBuilder();
        medicalInsuranceFormula_sb.append(medicalCardinal);
        medicalInsuranceFormula_sb.append("*0.02=");
        medicalInsuranceFormula_sb.append(medicalInsurance);
        calculateInsuranceRsp.setMedicalInsuranceFormula(medicalInsuranceFormula_sb.toString());

        // 失业
        BigDecimal careerInsuranceResult = socialCardinal.multiply(new BigDecimal("0.005"));
        BigDecimal careerInsurance = careerInsuranceResult.setScale(2, RoundingMode.CEILING);
        calculateInsuranceRsp.setCareerInsurance(careerInsurance);
        StringBuilder careerInsuranceFormula_sb = new StringBuilder();
        careerInsuranceFormula_sb.append("ROUNDUP(");
        careerInsuranceFormula_sb.append(socialCardinal);
        careerInsuranceFormula_sb.append("*0.005,2)=");
        careerInsuranceFormula_sb.append(careerInsurance);
        calculateInsuranceRsp.setCareerInsuranceFormula(careerInsuranceFormula_sb.toString());

        // 养老
        BigDecimal endowmentInsurance = socialCardinal.multiply(new BigDecimal("0.08"));
        calculateInsuranceRsp.setEndowmentInsurance(endowmentInsurance);
        StringBuilder endowmentInsuranceFormula_sb = new StringBuilder();
        endowmentInsuranceFormula_sb.append(socialCardinal);
        endowmentInsuranceFormula_sb.append("*0.08=");
        endowmentInsuranceFormula_sb.append(endowmentInsurance);
        calculateInsuranceRsp.setEndowmentInsuranceFormula(endowmentInsuranceFormula_sb.toString());

        // 职业年金
        BigDecimal occupationAnnuity = socialCardinal.multiply(new BigDecimal("0.04"));
        calculateInsuranceRsp.setOccupationAnnuity(occupationAnnuity);
        StringBuilder occupationAnnuityFormula_sb = new StringBuilder();
        occupationAnnuityFormula_sb.append(socialCardinal);
        occupationAnnuityFormula_sb.append("*0.04=");
        occupationAnnuityFormula_sb.append(occupationAnnuity);
        calculateInsuranceRsp.setOccupationAnnuityFormula(occupationAnnuityFormula_sb.toString());


        // 工会会费
        Long postId_2014;
        // 2014年标准不区分是否是教师，因此如果选择的教师系列，则需要转换成对应的非教师系列进行计算
        if (YesNoConstant.YES == systemPostPO.getIsTeachSeries()) {
            SystemPostPO systemPostPO_teacher = systemPostMapper.queryByTypeIdAndRankAndIsTeach(systemPostPO.getPostTypeId(), systemPostPO.getPostRank(), YesNoConstant.NO);
            if (null == systemPostPO_teacher) {
                calculateInsuranceRsp.setUnionDues(BigDecimal.valueOf(0));
                calculateInsuranceRsp.setUnionDuesFormula("无法计算");
                return ResultData.success(calculateInsuranceRsp);
            }
            postId_2014 = systemPostPO_teacher.getId();
        } else {
            postId_2014 = postId;
        }
        SystemPostSalaryPO systemPostSalaryPO_2014 = systemPostSalaryMapper.queryByPostIdAndModifyYear(postId_2014, YearConstant.YEAR_2014);
        if (null == systemPostSalaryPO_2014) {
            calculateInsuranceRsp.setUnionDues(BigDecimal.valueOf(0));
            calculateInsuranceRsp.setUnionDuesFormula("无法计算");
            return ResultData.success(calculateInsuranceRsp);
        }
        SystemLevelSalaryPO systemLevelSalaryPO_2014 = systemLevelSalaryMapper.queryByPostTypeIdAndRank(systemLevelSalaryPO.getPostTypeId(), systemLevelSalaryPO.getLevelRank(), YearConstant.YEAR_2014);
        if (null == systemLevelSalaryPO_2014) {
            calculateInsuranceRsp.setUnionDues(BigDecimal.valueOf(0));
            calculateInsuranceRsp.setUnionDuesFormula("无法计算");
            return ResultData.success(calculateInsuranceRsp);
        }
        Double unionDuesFormulaResult = (systemPostSalaryPO_2014.getPostSalary() / 100.00 + systemLevelSalaryPO_2014.getSalaryStandard() / 100.00) * 0.005;
        BigDecimal unionDuesFormula = BigDecimal.valueOf(unionDuesFormulaResult).setScale(2, RoundingMode.HALF_UP);
        calculateInsuranceRsp.setUnionDues(unionDuesFormula);
        StringBuilder unionDuesFormulaFormula_sb = new StringBuilder();
        unionDuesFormulaFormula_sb.append("ROUND((");
        unionDuesFormulaFormula_sb.append(systemPostSalaryPO_2014.getPostSalary() / 100);
        unionDuesFormulaFormula_sb.append("+");
        unionDuesFormulaFormula_sb.append(systemLevelSalaryPO_2014.getSalaryStandard() / 100);
        unionDuesFormulaFormula_sb.append(")*0.005,2)=");
        unionDuesFormulaFormula_sb.append(unionDuesFormula);
        calculateInsuranceRsp.setUnionDuesFormula(unionDuesFormulaFormula_sb.toString());

        return ResultData.success(calculateInsuranceRsp);
    }

    /**
     * 更新薪资
     *
     * @param updateSalaryReq
     * @return
     */
    @Override
    @Transactional
    public ResultData updateSalary(UpdateSalaryReq updateSalaryReq) {
        salaryComponent.updateSalary(updateSalaryReq);
        return ResultData.success();
    }

    /**
     * 新增薪资
     *
     * @param addSalaryReq
     * @return
     */
    @Override
    @Transactional
    public ResultData addSalary(AddSalaryReq addSalaryReq) {
        salaryComponent.createSalary(addSalaryReq);
        return ResultData.success();
    }

    /**
     * 定薪
     *
     * @param makeSalaryReq
     * @return
     */
    @Override
    @Transactional
    public ResultData makeSalary(MakeSalaryReq makeSalaryReq) {

        Integer dealResult = makeSalaryReq.getDealResult();
        if (null == dealResult) {
            throw new BusinessException("未指定处理结果", HttpStatus.BAD_REQUEST);
        }
        String rejectReason = makeSalaryReq.getRejectReason();
        if (FlowRecordDealResultEnum.REJECT.getCode() == makeSalaryReq.getDealResult() &&  null == rejectReason) {
            throw new BusinessException("未指定拒绝原因", HttpStatus.BAD_REQUEST);
        }

        Long userId = makeSalaryReq.getSalary().getUserId();
        if (null == userId) {
            throw new BusinessException("定薪人员未指定", HttpStatus.BAD_REQUEST);
        }
        UserBasicPO userBasicPO = userBasicMapper.queryById(userId);
        if (null == userBasicPO) {
            throw new BusinessException("人员不存在", HttpStatus.BAD_REQUEST);
        }
        if (UserSalaryStatusEnum.ON_APPROVE.getCode() != userBasicPO.getUserSalaryStatus()) {
            throw new BusinessException("无进行中的审批", HttpStatus.BAD_REQUEST);
        }
        Long flowId = userBasicPO.getSalaryFlowId();
        if (null == flowId) {
            throw new BusinessException("该用户的起薪审批流数据错误", HttpStatus.BAD_REQUEST);
        }

        // 如果是通过，则创建该人员的薪资
        if (FlowRecordDealResultEnum.PASS.getCode() == dealResult) {
            salaryComponent.createSalary(makeSalaryReq.getSalary());
        }

        // 维护流程信息
        Date date = new Date();
        FlowStatusEnum flowStatusEnum = flowComponent.auditFlow(flowId, date, dealResult, rejectReason);
        if (FlowStatusEnum.PASS.getCode() == flowStatusEnum.getCode()) {
            userBasicPO.setUserSalaryStatus(UserSalaryStatusEnum.PASS.getCode());
            userBasicMapper.updateById(userBasicPO);
        } else if (FlowStatusEnum.REJECT.getCode() == flowStatusEnum.getCode()) {
            userBasicPO.setUserSalaryStatus(UserSalaryStatusEnum.REJECT.getCode());
            userBasicMapper.updateById(userBasicPO);
            salaryMapper.deleteByUserId(userBasicPO.getId());
        }
        return ResultData.success();
    }

    /**
     * 复核定薪
     *
     * @param recheckSalaryReq
     * @return
     */
    @Override
    public ResultData recheckSalary(RecheckSalaryReq recheckSalaryReq) {
        Integer dealResult = recheckSalaryReq.getDealResult();
        if (null == dealResult) {
            throw new BusinessException("未指定处理结果", HttpStatus.BAD_REQUEST);
        }
        String rejectReason = recheckSalaryReq.getRejectReason();
        if (FlowRecordDealResultEnum.REJECT.getCode() == recheckSalaryReq.getDealResult() &&  null == rejectReason) {
            throw new BusinessException("未指定拒绝原因", HttpStatus.BAD_REQUEST);
        }

        Long userId = recheckSalaryReq.getSalary().getUserId();
        if (null == userId) {
            throw new BusinessException("定薪人员未指定", HttpStatus.BAD_REQUEST);
        }
        UserBasicPO userBasicPO = userBasicMapper.queryById(userId);
        if (null == userBasicPO) {
            throw new BusinessException("人员不存在", HttpStatus.BAD_REQUEST);
        }
        if (UserSalaryStatusEnum.ON_APPROVE.getCode() != userBasicPO.getUserSalaryStatus()) {
            throw new BusinessException("无进行中的审批", HttpStatus.BAD_REQUEST);
        }
        Long flowId = userBasicPO.getSalaryFlowId();
        if (null == flowId) {
            throw new BusinessException("该用户的起薪审批流数据错误", HttpStatus.BAD_REQUEST);
        }

        // 维护流程信息
        Date date = new Date();
        FlowStatusEnum flowStatusEnum = flowComponent.auditFlow(flowId, date, dealResult, rejectReason);
        if (FlowStatusEnum.PASS.getCode() == flowStatusEnum.getCode()) {
            userBasicPO.setUserSalaryStatus(UserSalaryStatusEnum.PASS.getCode());
            userBasicMapper.updateById(userBasicPO);
        } else if (FlowStatusEnum.REJECT.getCode() == flowStatusEnum.getCode()) {
            userBasicPO.setUserSalaryStatus(UserSalaryStatusEnum.REJECT.getCode());
            userBasicMapper.updateById(userBasicPO);
            salaryMapper.deleteByUserId(userBasicPO.getId());
        }
        return ResultData.success();
    }
}